import cv2
 
recognizer = cv2.face.LBPHFaceRecognizer_create()#使用局部二值模式直方图（LBPH）方法初始化人脸识别器。
recognizer.read('trainer/trainer.yml')#加载事先训练的模型文件 trainer.yml，包含不同人脸的特征数据。
cascadePath = "haarcascade_frontalface_default.xml"# OpenCV 提供的 Haar特征级联分类器 检测人脸。

faceCascade = cv2.CascadeClassifier(cascadePath)#加载 haarcascade_frontalface_default.xml 人脸检测模型
font = cv2.FONT_HERSHEY_SIMPLEX#定义文本字体，用于在图像上显示识别结果
id = 0#当前识别的人脸ID。

names = ['None', 'tsy', 'gy', 'Ilza', 'lyw', 'W']#names: 人脸ID和名称的对应列表，例如 id=1 对应 tsy，id=2 对应 ywl。
cam = cv2.VideoCapture(0)#打开摄像头（0表示默认摄像头）
cam.set(3, 1920)  # 设置摄像头捕捉视频的宽度和高度。
cam.set(4, 1080)

#minW = 0.1 * cam.get(3)#定义检测人脸的最小宽高（原始图像的10%），过滤掉过小的人脸。
#minH = 0.1 * cam.get(4)

minW = 300
minH = 300

prev_time = 0## 初始化帧率计算时间戳

while True:
    ret, img = cam.read()#ret: 捕获成功则为True img: 当前视频帧的图像数据
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#将图像转换为灰度（灰度图适合于Haar级联检测和LBPH识别）
    #人脸检测
    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.2,#图像缩放因子，越大越快但可能漏检
        minNeighbors=5,#每个候选矩形需检测到至少5次才被认为是人脸。
        minSize=(int(minW), int(minH)),#最小人脸尺寸，过滤过小区域
    )

    for (x, y, w, h) in faces:
        #rectangle: 参数 (x, y) 是左上角坐标，(x+w, y+h) 是右下角坐标。
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
        id, confidence = recognizer.predict(gray[y:y + h, x:x + w])
        if confidence < 100:
            id = names[id]
            confidence = "  {0}%".format(round(100 - confidence))
            print("check id is %d", id)
        else:
            id = "unknown"
            confidence = "  {0}%".format(round(100 - confidence))
        cv2.putText(img, str(id), (x + 5, y - 5), font, 1, (255, 255, 255), 2)
        cv2.putText(img, str(confidence), (x + 5, y + h - 5), font, 1, (255, 255, 0), 1)

    # 计算当前帧率（FPS）
    curr_time = cv2.getTickCount()
    fps = cv2.getTickFrequency() / (curr_time - prev_time)
    prev_time = curr_time

    # 在视频中显示当前FPS
    cv2.putText(img, f"FPS: {fps:.2f}", (10, 30), font, 1, (0, 0, 255), 2)
    cv2.imshow('camera', img)
    k = cv2.waitKey(10) & 0xFF  # Press 'ESC' for exiting video

    if k == 27:
        break

# Do a bit of cleanup
print("\n [INFO] Exiting Program and cleanup stuff")
cam.release()

cv2.destroyAllWindows()